﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO.Ports;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading.Tasks;
using System.Web.Http;
using System.Web.UI.WebControls.WebParts;
using JGSoft.U9CRTAPIEX.DTOs;
using JGSoft.U9CRTAPIEX.DTOs.RequestDTOs;
using JGSoft.U9CRTAPIEX.DTOs.ResultDTOs;
using JGSoft.U9CRTAPIEX.Public;
using Newtonsoft.Json;
using UFIDA.U9.AP.APBill;
using UFIDA.U9.AP.APBill.Proxy;
using UFIDA.U9.AP.ForAPI;
using UFIDA.U9.Base;
using UFIDA.U9.Base.Currency;
using UFIDA.U9.Base.Doc;
using UFIDA.U9.Base.PropertyTypes;
using UFIDA.U9.CBO.FI.CommonFIHelper;
using UFIDA.U9.CBO.FI.ConfirmTerm;
using UFIDA.U9.CBO.FI.DTOs;
using UFIDA.U9.CBO.FI.Enums;
using UFIDA.U9.CBO.FI.Tax;
using UFIDA.U9.CBO.FI_SCM.DTOs;
using UFIDA.U9.CBO.Pub.Controller;
using UFIDA.U9.CBO.SCM.Item;
using UFIDA.U9.CBO.SCM.ProjectTask;
using UFIDA.U9.CBO.SCM.Supplier;
using UFIDA.U9.ISV.AP;
using UFIDA.U9.ISV.PO;
using UFIDA.U9.ISV.PO.Proxy;
using UFIDA.U9.PM.PO;
using UFIDA.U9.PM.Rcv;
using UFIDA.U9.PM.Rtn;
using UFIDA.U9.SM.Ship;
using UFSoft.UBF.AopFrame.Lock;
using UFSoft.UBF.Business;
using UFSoft.UBF.MVC;
using UFSoft.UBF.MVC.Common;
using UFSoft.UBF.UI.Portal.OAuth2;
using UFSoft.UBF.Util.DataAccess;
using static UFSoft.UBF.MVC.ZApi.Model.ZAssemblySummary.Member;

namespace JGSoft.U9CRTAPIEX.Controllers
{
    public class SRMController : ApiController
    {
        private readonly string _userCode;
        private readonly string _entCode;
        private readonly string _orgCode;
        public SRMController()
        {
            JsonConfig _config = new JsonConfig();
            _userCode = _config.SelectToken("UserCode");
            _entCode = _config.SelectToken("EntCode");
            _orgCode = _config.SelectToken("OrgCode");
        }

        /// <summary>
        /// SRM采购订单确认状态回写
        /// </summary>
        /// <param name="paras"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResult<List<ResultBase>> POConfirm([FromBody] List<StatuConfirmPara> paras)
        {
            using (BPForEngine bp = new BPForEngine())
            {
                ContextDTO tdto = new ContextDTO();
                tdto.UserCode = _userCode;//取接口传入的用户编码
                tdto.EntCode = _entCode;//取接口传入的企业编码
                tdto.CultureName = "zh-CN";//固定
                tdto.OrgCode = _orgCode;//取接口传入的组织编码
                tdto.WriteToContext();
                ApiResult<List<ResultBase>> result = new ApiResult<List<ResultBase>>();
                List<ResultBase> rtndatas = new List<ResultBase>();
                LogManager.WriteLog(JsonConvert.SerializeObject(paras), "SRMRequest");
                try
                {
                    var PODocNos = paras.Select(t => t.Code).Distinct().ToList();
                    var POs = PurchaseOrder.Finder.FindAll($"DocNo in ({PublicMethod.StringJoin(PODocNos)})").Cast<PurchaseOrder>().ToList();
                    var noExist = PODocNos.Except(POs.Select(t=>t.DocNo)).ToList();
                    if(noExist.Any())
                    {
                        result.ResCode = 1;
                        result.ResMsg = $"未找到订单 {string.Join(",", noExist)}";
                        LogManager.WriteLog($"未找到订单  {string.Join(",", noExist)}", "All");
                        return result;
                    }
                    using (ISession session = Session.Open())
                    {
                        foreach (var po in POs)
                        {
                            //var po = PurchaseOrder.Finder.Find($"ID = {para.ID} or DocNo = '{para.Code}'");
                            if (po.Status.Value < 2)
                            {
                                result.ResCode = 1;
                                result.ResMsg = $"订单{po.DocNo}未审核";
                                LogManager.WriteLog($"订单{po.DocNo}未审核", "All");
                                return result;
                            }

                            var IsConfirm = paras.FirstOrDefault(t => t.Code == po.DocNo).IsConfirm;
                            if (IsConfirm == true)
                                po.DescFlexField.PrivateDescSeg2 = "True";
                            else
                                po.DescFlexField.PrivateDescSeg2 = "False";

                            rtndatas.Add(new ResultBase { IsSucess = true, ID = po.ID });
                        }
                        session.Commit();
                    }
                    result.Data = rtndatas;
                    return result;
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        /// <summary>
        /// SRM采购计划确认状态回写
        /// </summary>
        /// <param name="paras"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResult<List<ResultBase>> PRConfirm([FromBody] List<StatuConfirmPara> paras)
        {
            using (BPForEngine bp = new BPForEngine())
            {
                ContextDTO tdto = new ContextDTO();
                tdto.UserCode = _userCode;//取接口传入的用户编码
                tdto.EntCode = _entCode;//取接口传入的企业编码
                tdto.CultureName = "zh-CN";//固定
                tdto.OrgCode = _orgCode;//取接口传入的组织编码
                tdto.WriteToContext();
                ApiResult<List<ResultBase>> result = new ApiResult<List<ResultBase>>();
                List<ResultBase> rtndatas = new List<ResultBase>();
                try
                {

                    foreach (var para in paras)
                    {
                        var po = UFIDA.U9.PR.PurchaseRequest.PR.Finder.Find($"ID = {para.ID} or DocNo = '{para.Code}'");
                        if (po != null)
                        {
                            using (ISession session = Session.Open())
                            {
                                if (para.IsConfirm == true)
                                    po.DescFlexField.PrivateDescSeg1 = "True";
                                else
                                    po.DescFlexField.PrivateDescSeg1 = "False";
                                session.Commit();
                            }
                            rtndatas.Add(new ResultBase { IsSucess = true, ID = po.ID });
                        }
                        else
                        {
                            result.ResCode = 1;
                            result.ResMsg = $"未找到订单{para.Code}";
                        }
                    }
                    result.Data = rtndatas;
                    return result;
                }
                catch (Exception ex)
                {
                    throw new Exception(ex.Message);
                }
            }
        }

        /// <summary>
        /// 采购订单行关闭
        /// </summary>
        /// <param name="paras"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResult<List<ResultBase>> POLineClose([FromBody] List<IDCodePara> paras)
        {
            using (BPForEngine bp = new BPForEngine())
            {
                ContextDTO tdto = new ContextDTO();
                tdto.UserCode = _userCode;//取接口传入的用户编码
                tdto.EntCode = _entCode;//取接口传入的企业编码
                tdto.CultureName = "zh-CN";//固定
                tdto.OrgCode = _orgCode;//取接口传入的组织编码
                tdto.WriteToContext();
                ClosePOLineSRVProxy sv = new ClosePOLineSRVProxy();
                ApiResult<List<ResultBase>> result = new ApiResult<List<ResultBase>>();
                List<ResultBase> rtndatas = new List<ResultBase>();
                //try
                //{
                //    var svparas = new List<POLineKeyDTOData>();
                //    foreach (var para in paras)
                //    {
                //        var poshipline = POShipLine.Finder.FindByID(para.ID);
                //        if (poshipline != null)
                //        {
                //            svparas.Add(new POLineKeyDTOData() { LineKeyDTO = new UFIDA.U9.Base.DTOs.IDCodeNameDTOData() { ID = poshipline.POLine.ID } });
                //            rtndatas.Add(new ResultBase { IsSucess = true, ID = para.ID });
                //        }
                //    }
                //    sv.POLineKeyDTOs = svparas;
                //    if (svparas.Count > 0)
                //        sv.Do();
                //    result.Data = rtndatas;
                //    return result;
                //}
                //catch (Exception ex)
                //{
                //    throw new Exception(ex.Message);
                //}
                LogManager.WriteLog("POLineClose废弃接口被调用", "SRMRequest");
                throw new Exception("该接口已弃用，请修改接口地址");
            }
        }

        [HttpPost]
        public ApiResult<string> CreateAPBill([FromBody] List<CreateAPPara> paras)
        {
            LogManager.WriteLog(JsonConvert.SerializeObject(paras), "SRMRequest");
            using (BPForEngine bp = new BPForEngine())
            {
                ContextDTO tdto = new ContextDTO();
                tdto.UserCode = _userCode;//取接口传入的用户编码
                tdto.EntCode = _entCode;//取接口传入的企业编码
                tdto.CultureName = "zh-CN";//固定
                tdto.OrgCode = _orgCode;//取接口传入的组织编码
                tdto.WriteToContext();
                ApiResult<string> result = new ApiResult<string>();
                List<long> sucIDs = new List<long>();
                APAccrueAPISV sv = new APAccrueAPISV();
                Stopwatch sw = Stopwatch.StartNew();
                DataAccessor.RunSQL(DataAccessor.GetConn(), $@"select sche.ID,sche.Code,sum(tax1.TaxRate) TaxRate
from CBO_TaxSchedule sche
inner join CBO_TaxScheduleTax tax on tax.TaxSchedule = sche.ID
inner join CBO_Tax tax1 on tax1.ID = tax.Tax
where sche.Effective_IsEffective = 1
group by sche.ID,sche.Code", null, out DataSet taxDs);
                try
                {
                    foreach (var para in paras)
                    {
                        var suppSite = SupplierSite.Finder.Find($"Supplier.Code = '{para.AccrueSuppCode}'");
                        para.AccrueSuppSiteCode = suppSite.Code;
                        para.PaySuppSiteCode = suppSite.Code;
                        Currency currency = Currency.Finder.Find($"Code = '{para.ACCode}' or Symbol = '{para.ACCode}'");
                        para.ACCode = currency.Code;

                        List<string> srcRcvDocNo = para.ImportAPBillLineDTOs.Select(t => t.SrcDocNo).ToList();
                        var srcAPBillHeads = Receivement.Finder.FindAll($"DocNo in ({string.Join(",", srcRcvDocNo.Select(t => $"'{t}'"))})");

                        var apheaddto = new AccrueAPIDTO();
                        apheaddto.AccrueDate = para.AccrueDate;
                        apheaddto.CusOrSuppCode = para.AccrueSuppCode;
                        apheaddto.CusOrSuppSiteCode = para.AccrueSuppSiteCode;
                        apheaddto.FIOrg = Context.LoginOrg.ID;
                        apheaddto.SrcOrg = Context.LoginOrg.ID;
                        apheaddto.IsMerge = true;
                        apheaddto.APMergConfigDTO = new APMergeAccrueCfgDTO()
                        {
                            IsAccrueTerm = true,
                            IsMaturity = true,
                            IsProject = true,
                            IsTask = true
                        };
                        apheaddto.ARMergConfigDTO = new ARMergeAccrueCfgDTO();
                        apheaddto.Currency = currency.ID;
                        apheaddto.InvoiceNum = para.InvoiceNum;
                        apheaddto.InvoiceDate = para.InvoiceDate;
                        apheaddto.Memo = para.Memo;
                        var aplines = new List<AccrueDetailAPIDTO>();
                        apheaddto.AccrueDetailDTOs = aplines;
                        foreach (var line in para.ImportAPBillLineDTOs)
                        {
                            AccrueDetailAPIDTO aplinedto = new AccrueDetailAPIDTO();
                            var srcRcvHead = srcAPBillHeads.Cast<Receivement>().FirstOrDefault(t => t.DocNo == line.SrcDocNo);
                            var srcRcvline = srcRcvHead.RcvLines.Cast<RcvLine>().FirstOrDefault(t => t.DocLineNo == Convert.ToInt32(line.SrcLineNum));
                            if (srcRcvHead != null)
                            {
                                line.SrcBusinessType = srcRcvHead.BizType.Value;
                                if (line.SrcBusinessType == 321)
                                    line.SrcBusinessType = 322;
                            }
                            else
                                line.SrcBusinessType = 316;

                            //decimal.Round(xx,2,MidpointRounding.AwayFromZero)
                            aplinedto.LineID = srcRcvline.ID;
                            decimal taxRate = Convert.ToDecimal(line.TaxScheduleCode);
                            decimal AbsAmount = Math.Abs(line.PUAmount);
                            decimal AbsMoney = Math.Abs(line.Money);
                            aplinedto.Amount = AbsAmount;
                            aplinedto.NoTaxPrice = line.UnitPrice;
                            aplinedto.TaxPrice = line.TaxPrice;
                            aplinedto.TaxMoney = Math.Abs(line.TaxMoney);
                            aplinedto.NoTaxMoney = Math.Abs(line.NoTaxMoney);
                            aplinedto.TotalMoney = AbsMoney;
                            long taxSceduleID = srcRcvline.TaxSchedule?.ID ?? Convert.ToInt64(taxDs.Tables[0].Select($"TaxRate = '{line.TaxScheduleCode}'")[0]["ID"]);
                            aplinedto.TaxScedule = taxSceduleID;
                            //aplinedto.TaxScedule = srcRcvline.TaxSchedule?.ID ?? 0;
                            if (line.PUAmount >= 0)
                                aplinedto.IsRMA = true;
                            else
                                aplinedto.IsRMA = false;
                            aplines.Add(aplinedto);
                        }
                        sv.AccrueAPIDTO = apheaddto;
                        var group = para.ImportAPBillLineDTOs.GroupBy(t => new { t.SrcBusinessType, t.ItemInfo.ItemCode }).Where(t => t.Sum(u => u.Money) < 0).Count();
                        if (group > 0)
                            apheaddto.IsMerge = false;
                        LogManager.WriteLog($"创建应付单数据处理：{sw.ElapsedMilliseconds / 1000}", "SRMRequest");
                        sw.Restart();
                        var svResult = sv.Do();
                        LogManager.WriteLog($"创建应付单APAccrueAPISV执行时间：{sw.ElapsedMilliseconds / 1000}", "SRMRequest");
                        sw.Restart();
                        if (svResult != null)
                        {
                            sucIDs.AddRange(svResult);
                            var project = Project.Finder.Find($"Code = '{para.ProjectCode}' or Name = '{para.ProjectCode}'");
                            //foreach (var item in svResult)
                            //{
                            //    APBillHead head = APBillHead.Finder.FindByID(item);
                            //    //head.Memo = para.Memo;
                            //    //var transEntrys = UFIDA.U9.AAI.TransEntry.TransactionEntry.Finder.FindAll($"OriginalPrimaryEntity.EntityID = {item}");
                            //    //foreach (var transEntry in transEntrys)
                            //    //{
                            //    //    transEntry.AbstractT = para.Memo;
                            //    //}
                            //    foreach (var line in head.APBillLines)
                            //    {
                            //        line.Project = project;
                            //    }
                            //}
                            //session.Commit();
                            DataAccessor.RunSQL(DataAccessor.GetConn(), $@"
update AP_APBillLine set Project = {project.ID} where ID in(
select apline.ID from AP_APBillHead ap
inner join AP_APBillLine apline on apline.APBillHead = ap.ID
where ap.ID in ({string.Join(",", sucIDs)}))", null, out DataSet _);
                        }
                    }
                    result.Data = string.Join(",", sucIDs.Select(t => t.ToString()));
                    sw.Stop();
                    LogManager.WriteLog($"创建应付单赋值项目时间：{sw.ElapsedMilliseconds / 1000}", "SRMRequest");
                    return result;
                }
                catch (Exception ex)
                {
                    LogManager.WriteLog(ex.Message + "\r\n" + ex.StackTrace, "All");
                    result.ResCode = 1;
                    result.ResMsg = ex.Message;
                    return result;
                }
            }
        }

        [HttpPost]
        public ApiResult<string> UpdateSRMQty([FromBody] List<UpdateSRMQtyPara> paras)
        {
            ApiResult<string> result = new ApiResult<string>();
            //using (BPForEngine bp = new BPForEngine())
            //{
            //    ContextDTO tdto = new ContextDTO();
            //    tdto.UserCode = _userCode;//取接口传入的用户编码
            //    tdto.EntCode = _entCode;//取接口传入的企业编码
            //    tdto.CultureName = "zh-CN";//固定
            //    tdto.OrgCode = _orgCode;//取接口传入的组织编码
            //    tdto.WriteToContext();

            //    try
            //    {
            //        LogManager.WriteLog(JsonConvert.SerializeObject(paras), "SRMRequest");
            //        var DocNoList = paras.Select(t => $"'{t.DocNo}'");
            //        var polines = POLine.Finder.FindAll($"PurchaseOrder.DocNo in ({string.Join(",", DocNoList)})").Cast<POLine>();
            //        using (ISession session = Session.Open())
            //        {

            //            foreach (var para in paras)
            //            {
            //                string docLineNo = para.DocLineNo.ToString();
            //                if (docLineNo.Length > 5)
            //                    docLineNo = docLineNo.Substring(0, docLineNo.Length - 5);
            //                var poline = polines.FirstOrDefault(t => t.PurchaseOrder.DocNo == para.DocNo && t.DocLineNo == Convert.ToInt32(docLineNo));
            //                if (string.IsNullOrEmpty(poline.DescFlexSegments?.PrivateDescSeg6))
            //                    poline.DescFlexSegments.PrivateDescSeg6 = para.Qty.ToString();
            //                else
            //                    poline.DescFlexSegments.PrivateDescSeg6 = (Convert.ToDecimal(poline.DescFlexSegments?.PrivateDescSeg6) + para.Qty).ToString();
            //                //生产订单勾选已送货
            //                List<string> moDocNoList = poline.DescFlexSegments.PrivateDescSeg9.Split(',').Select(t => t.Split('_')[0]).ToList();
            //                var moList = UFIDA.U9.MO.MO.MO.Finder.FindAll($"DocNo in ({string.Join(",", moDocNoList.Select(t => $"'{t}'"))})").Cast<UFIDA.U9.MO.MO.MO>();
            //                if (Convert.ToDecimal(poline.DescFlexSegments?.PrivateDescSeg6) != 0)
            //                {
            //                    foreach (var mo in moList)
            //                    {
            //                        mo.DescFlexField.PrivateDescSeg6 = "True";
            //                    }
            //                }
            //                else
            //                {
            //                    foreach (var mo in moList)
            //                    {
            //                        var moPolines = POLine.Finder.FindAll($"DescFlexSegments.PrivateDescSeg9 like '%{mo.DocNo}%'").Cast<POLine>();
            //                        bool allZero = true;
            //                        foreach (var moPOline in moPolines)
            //                        {
            //                            if (Convert.ToDecimal(poline.DescFlexSegments?.PrivateDescSeg6) != 0)
            //                            {
            //                                allZero = false;
            //                                break;
            //                            }
            //                        }
            //                        if (allZero)
            //                            mo.DescFlexField.PrivateDescSeg6 = "False";
            //                    }
            //                }
            //            }
            //            session.Commit();
            //        }
            //        return result;
            //    }
            //    catch (Exception ex)
            //    {
            //        LogManager.WriteLog(ex.Message + "\r\n" + ex.StackTrace, "All");
            //        result.ResCode = 1;
            //        result.ResMsg = ex.Message;
            //        return result;
            //    }
            //}
            return result;
        }

        /// <summary>
        /// SRM关闭部分数量
        /// </summary>
        /// <param name="paras"></param>
        /// <returns></returns>
        [HttpPost]
        public ApiResult<List<ResultBase>> ClosePOQty([FromBody] List<ClosePOQtyPara> paras)
        {
            LogManager.WriteLog(JsonConvert.SerializeObject(paras), "SRMRequest");
            ApiResult<List<ResultBase>> result = new ApiResult<List<ResultBase>>();
            List<ResultBase> rtndatas = new List<ResultBase>();
            using (BPForEngine bp = new BPForEngine())
            {
                ContextDTO tdto = new ContextDTO();
                tdto.UserCode = _userCode;//取接口传入的用户编码
                tdto.EntCode = _entCode;//取接口传入的企业编码
                tdto.CultureName = "zh-CN";//固定
                tdto.OrgCode = _orgCode;//取接口传入的组织编码
                tdto.WriteToContext();

                Dictionary<long, decimal> paraDict = new Dictionary<long, decimal>();
                foreach (var para in paras)
                {
                    paraDict.Add(para.ID, para.Qty);
                }
                var paraIDs = paras.Select(t => t.ID);
                List<POShipLine> poshiplines = POShipLine.Finder.FindAll($"ID in ({string.Join(",", paraIDs)})").Cast<POShipLine>().ToList();
                var except = paraIDs.Except(poshiplines.Select(t => t.ID));
                if (except.Count() > 0)
                {
                    result.ResCode = 1;
                    result.ResMsg = $"未找到ID {string.Join(",", except)}的采购计划行";
                    return result;
                }
                using (ISession session = Session.Open())
                {
                    if (poshiplines.Count > 0)
                    {
                        foreach (var shipline in poshiplines)
                        {
                            var clostQty = paraDict[shipline.ID];
                            shipline.DescFlexSegments.PrivateDescSeg1 = $"{clostQty:F2}";
                            if (shipline.ReqQtyTU > clostQty)
                            {
                                shipline.SupplierConfirmQtyTU = shipline.ReqQtyTU - clostQty;
                                shipline.SupplierConfirmQtyPU = shipline.ReqQtyTU - clostQty;
                                shipline.SupplierConfirmQtyCU = shipline.ReqQtyTU - clostQty;
                                shipline.POLine.SupplierConfirmQtyTU = shipline.ReqQtyTU - clostQty;
                                shipline.POLine.SupplierConfirmQtyPU = shipline.ReqQtyTU - clostQty;
                                shipline.POLine.SupplierConfirmQtyCU = shipline.ReqQtyTU - clostQty;
                            }
                            rtndatas.Add(new ResultBase { ID = shipline.ID, IsSucess = true });
                        }
                    }
                    session.Commit();
                }
                ClosePOLineSRVProxy sv = new ClosePOLineSRVProxy();
                var svparas = new List<POLineKeyDTOData>();
                var polines = poshiplines.Select(t => t.POLine).ToList();
                foreach (var poline in polines)
                {
                    var shilines = poline.POShiplines.Cast<POShipLine>();
                    if (shilines.Sum(t => t.RcvQtyTU) + shilines.Sum(t => DictTryGetValue(paraDict, t.ID)) >= shilines.Sum(t => t.ReqQtyTU))
                    {
                        svparas.Add(new POLineKeyDTOData() { LineKeyDTO = new UFIDA.U9.Base.DTOs.IDCodeNameDTOData() { ID = poline.ID } });
                    }
                }
                sv.POLineKeyDTOs = svparas;
                if (svparas.Count > 0)
                    sv.Do();
            }
            result.Data = rtndatas;
            return result;
        }
        private decimal DictTryGetValue(Dictionary<long, decimal> Dict, long key)
        {
            Dict.TryGetValue(key, out decimal qty);
            return qty;
        }
    }
}
